package com.deer.backup.scheduling;

import java.io.File;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import com.deer.backup.service.BackUpService;
import com.deer.backup.service.SetupsService;
import com.deer.backup.utils.CommonUtils;
import com.deer.backup.utils.SshjUtils;
import com.deer.backup.vo.BackUp;
import com.deer.backup.vo.RemoteVo;
import com.deer.backup.vo.Setups;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import net.schmizz.sshj.SSHClient;

/**
 * 服务备份定时任务配置
 * @author deer
 * @date 2023年4月20日
 */
@Slf4j
@Configuration // 标记配置类，兼备Component的效果
@EnableScheduling // 开启定时任务
public class BackUpScheduling {
	
	@Autowired
	private BackUpService backUpService;
	
	@Autowired
	private SetupsService setupsService;

	// 全局备份信息列表
	private static List<BackUp> backUpList;
	
	private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss"); // 定义时间格式
	
	// 全局文件保存份数
	private static int retainNum = 3;
	
	// 全局文件清理时间
	private static LocalTime clearTime = LocalTime.parse("00:00:00", formatter);
	
	/**
	 * 30秒更新一次缓冲数据
	 * @author deer
	 * @date 2023年4月20日
	 */
	@Scheduled(fixedRate = 30000)
	public void updateCache() {
		backUpList = backUpService.findBackUp();
		Setups setups = setupsService.getOne();
		if(StrUtil.isNotBlank(setups.getRetainNum())) {
			retainNum = Integer.valueOf(setups.getRetainNum());
		}
		if(StrUtil.isNotBlank(setups.getClearTime())){
			clearTime = LocalTime.parse(setups.getClearTime(), formatter);
		}
	}

	/**
	 * 清除备份文件任务
	 * @author deer
	 * @date 2023年5月4日
	 */
	@Scheduled(fixedRate = 1000)
	private void clearOldFile() {
		// 获取当前时间
		LocalTime nowTime = LocalTime.parse(LocalTime.now().format(formatter));
		// 判断是否相等
		if (nowTime.equals(clearTime)) {
			if (backUpList != null && backUpList.size() > 0) {
				for (BackUp backUp : backUpList) {
					File file = new File(backUp.getDirPath());
					// 文件或文件夹是否存在
					if (file.exists()) {
						// 判断是否是目录
						// 获得文件里面所有的文件及文件夹
						File[] files = file.listFiles();
				        if (files != null && files.length > 0) {
				        	// 对子文件夹按修改时间进行排序
					        Arrays.sort(files, Comparator.comparingLong(File::lastModified).reversed());
							// 保留最近的N个子文件，将其余的文件删除
					        for (int i = retainNum; i <= files.length; i++) {
					        	delFile(files[i]);
					        }
						}
					}
				}
			}
			log.info(DateUtil.now() + "==>文件清理完毕！");
		}
	}
	
	/**
	 * 服务备份任务
	 * @author deer
	 * @date 2023年5月4日
	 */
	@Scheduled(fixedRate = 1000)
	public void backUpTasks() {
		// 获取当前时间
        LocalTime nowTime = LocalTime.parse(LocalTime.now().format(formatter));
		if(backUpList != null && backUpList.size() > 0) {
			for (BackUp backUp : backUpList) {
		        LocalTime backUpTime = LocalTime.parse(backUp.getBackupTime(), formatter);
		        // 判断是否相等
		        if (nowTime.equals(backUpTime)) {
		            // 线程异步处理，防止主线程阻塞
		        	new Thread(() -> {
		        		try {
		        			RemoteVo remote = new RemoteVo();
		        			remote.setHost(backUp.getServerHost());
		        			remote.setUser(backUp.getServerUser());
		        			remote.setPassword(backUp.getServerPwd());
		        			SSHClient sshClient = SshjUtils.getConnect(remote);
		        			if (sshClient.isConnected()) {
		        				log.info(DateUtil.now() + "==>开始执行 " + backUp.getName() + " 任务");
		        				// 生成文件名称
		        				String backUpFile = backUp.getBackupName() + ".tar.gz";
		        				// 压缩home文件夹
		        				SshjUtils.remoteExecute(sshClient, "tar -zcvf " + backUpFile + " " + backUp.getServerPath());
		        				SshjUtils.sftpDownload(sshClient, "/root/" + backUpFile , CommonUtils.createDir(backUp.getDirPath()) + "/" + backUpFile);
		        				// 删除服务端压缩包
		        				SshjUtils.remoteExecute(sshClient, "rm -f " + backUpFile);
		        				// 关闭连接
		        				sshClient.disconnect();
		        				log.info(DateUtil.now() + "==>完成 " + backUp.getName() + " 任务");
		        			} else {
		        				log.error(backUp.getServerHost()+" 连接失败！");
		        			}
		        		} catch (Exception e) {
		        			log.error("定时备份异常:", e);
		        		}
		        	}).start();
		        }
			}
		}
	}

	/**
	 * 递归删除文件
	 * @author deer
	 * @date 2022年6月22日
	 * @param file
	 */
	public static void delFile(File file) {
		if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (File f : files) {
                	delFile(f);
                }
            }
        }
		file.delete();
	}
	
}
